using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Terminal.Advanced_AEUC_settings_controls.Settings_Interfaces;
using Terminal.Advanced_AEUC_settings_controls.Settings_AUX;
using Auxiliaries;

namespace Terminal.Advanced_AEUC_settings_controls.Settings_Editing_Forms
{
    /// <summary>
    /// Form for creating linked control groups
    /// </summary>
    public partial class AEUCLinkSettings : Form
    {
        /// <summary>
        /// Constructor taking a control array input
        /// </summary>
        /// <param name="inputSettings">The controls that will be linked</param>
        public AEUCLinkSettings(List<IAEUCSetting> inputSettings)
        {
            InitializeComponent();

            lbSelectedControlsView.DisplayMember = "AEUC_DisplayName";

            for (int i =0; i < inputSettings.Count; i++)
            {
                lbSelectedControlsView.Items.Add(inputSettings[i]);
            }

            lbSelectedControlsView.SelectedIndex = 0;
        }

        private void lbSelectedControlsView_SelectedValueChanged(object sender, EventArgs e)
        {
            IAEUCSetting tmpSetting = (IAEUCSetting)lbSelectedControlsView.Items[lbSelectedControlsView.SelectedIndex];
            tbID.Text = tmpSetting.AEUC_Id.ToString();
            tbSize.Text = tmpSetting.AEUC_Size.ToString();
            tbMaxVal.Text = tmpSetting.AEUC_Max.ToString();
            tbMinVal.Text = tmpSetting.AEUC_Min.ToString();
            if (rbBitMask.Checked)
                tbCalcedVal.Text = tmpSetting.AEUC_Val.ToString();
        }

        private void tbSize_TextChanged(object sender, EventArgs e)
        {
            uint new_size;
            bool faulty_input = false;
            if (!uint.TryParse(tbSize.Text, out new_size))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbSize.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    new_size = (uint)tmpVal;
            }
            if (!faulty_input)
            {
                new_size = new_size*8;
                uint max_value = 1;
                for (int i = 1; i<new_size; i++)
                {
                    uint power_of_two = 1;
                    for (int k = 0; k<i; k++)
                    {
                        power_of_two = power_of_two*2;
                    }
                    max_value += power_of_two;
                }

                tbMaxVal.Text = max_value.ToString();
            }
        }

        private void btnUnify_Click(object sender, EventArgs e)
        {
            grbBitfield.Visible = false;
            grbConsVals.Visible = false;
            pnlSetValue.Visible = false;

            uint id;
            uint size;
            uint max;
            uint min;
            bool faulty_input = false;

            if (!uint.TryParse(tbID.Text, out id))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbID.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    id = (uint)tmpVal;
            }
            if (!uint.TryParse(tbSize.Text, out size))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbSize.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    size = (uint)tmpVal;
            }
            if (!uint.TryParse(tbMaxVal.Text, out max))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbMaxVal.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    max = (uint)tmpVal;
            }
            if (!uint.TryParse(tbMinVal.Text, out min))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbMinVal.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    min = (uint)tmpVal;
            }

            if (!faulty_input)
            {
                for (int i =0; i < lbSelectedControlsView.Items.Count; i++)
                {
                    IAEUCSetting tmpSetting = (IAEUCSetting)lbSelectedControlsView.Items[i];
                    tmpSetting.AEUC_Id = id;
                    tmpSetting.AEUC_Size = size;
                    tmpSetting.AEUC_Max = (int)max;
                    tmpSetting.AEUC_Min = (int)min;
                }

                #region Open the settings for the specified link type
                //Disable as there is no more meaning to change it
                grbLinkType.Enabled = false;
                if (rbBitMask.Checked)
                {
                    #region Bitmask link
                    tbCalcedVal.TextChanged -= new EventHandler(tbCalcedVal_TextChanged);
                    pnlBitfield.Controls.Clear();
                    grbBitfield.Visible = true;
                    pnlSetValue.Visible = true;
                    tbCalcedVal.Text = "0";
                    uint num_bits = size*8;
                    CheckBox cht;
                    for (int i =0; i<num_bits; i++)
                    {
                        cht = new CheckBox();

                        if (pnlBitfield.Controls.Count > 0)
                            cht.Location = new Point(pnlBitfield.Controls[i -1].Location.X + pnlBitfield.Controls[i-1].Size.Width, pnlBitfield.Controls[i-1].Location.Y);

                        cht.Name = cht.Text = i.ToString();
                        if (i < 10)
                            cht.Size = new Size(35, 20);
                        else
                            cht.Size = new Size(45, 20);
                        cht.CheckedChanged += new EventHandler(cht_CheckedChanged);
                        pnlBitfield.Controls.Add(cht);
                    }
                    tbCalcedVal.TextChanged += new EventHandler(tbCalcedVal_TextChanged);
                    #endregion
                }
                else if (rbConsecutive.Checked)
                {
                    #region Consecutive link
                    trbBitPositions.Maximum = ((int.Parse(tbSize.Text) * 8) - 1);
                    grbConsVals.Visible = true;
                    pnlSetValue.Visible = true;
                    #endregion
                }
                #endregion
            }
        }

        #region Bitfield control options
        void cht_CheckedChanged(object sender, EventArgs e)
        {
            tbCalcedVal.TextChanged -= new EventHandler(tbCalcedVal_TextChanged);
            CheckBox tmpr = (CheckBox)sender;
            uint bit_place;
            uint cur_bitfield;
            bool faulty_input = false;

            if (!uint.TryParse(tmpr.Text, out bit_place))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbID.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    bit_place = (uint)tmpVal;
            }

            if (!faulty_input)
            {
                if (!uint.TryParse(tbCalcedVal.Text, out cur_bitfield))
                {
                    UInt64 tmpVal;
                    faulty_input = !HEX_converter.ToBinary(tbCalcedVal.Text, out tmpVal);
                    if (faulty_input)
                        MessageBox.Show("Please type a correct id value.");
                    else
                        cur_bitfield = (uint)tmpVal;
                }
                if(faulty_input)
                    cur_bitfield = 0;

                if(tmpr.Checked)
                    cur_bitfield |= (uint)(1<<(int)bit_place);
                else
                    cur_bitfield &= (uint)~(1 << (int)bit_place);

                

                tbCalcedVal.Text = cur_bitfield.ToString();
            }
            tbCalcedVal.TextChanged += new EventHandler(tbCalcedVal_TextChanged);
        }

        private void btnSetBitVal_Click(object sender, EventArgs e)
        {
            uint calced_val;
            bool faulty_input = false;

            if (!uint.TryParse(tbCalcedVal.Text, out calced_val))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbCalcedVal.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    calced_val = (uint)tmpVal;
            }
            if (!faulty_input)
            {
                IAEUCSetting tmpSetting = (IAEUCSetting)lbSelectedControlsView.Items[lbSelectedControlsView.SelectedIndex];
                tmpSetting.AEUC_Val = calced_val;
                tmpSetting.AEUC_Default = calced_val;
                tmpSetting.AEUC_Max = calced_val;
                
                //if (trbBitPositions.Value > 1)
                    tmpSetting.AEUC_Min = 1 << (trbBitPositions.Value);
                //else if (trbBitPositions.Value == 1)
                    //tmpSetting.AEUC_Min = 1;
                //else
                    //tmpSetting.AEUC_Min = 0;
            }
            else
            {
                MessageBox.Show("Please type a correct value.");
            }
        }

        private void tbCalcedVal_TextChanged(object sender, EventArgs e)
        {
            uint number = 0;
            uint size = 0;
            bool faulty_input = false;

            if (!uint.TryParse(tbCalcedVal.Text, out number))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbCalcedVal.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    number = (uint)tmpVal;
            }
            if (!faulty_input && !uint.TryParse(tbSize.Text, out size))
            {
                UInt64 tmpVal;
                faulty_input = !HEX_converter.ToBinary(tbSize.Text, out tmpVal);
                if (faulty_input)
                    MessageBox.Show("Please type a correct id value.");
                else
                    size = (uint)tmpVal;
            }
            if (!faulty_input)
            {
                size = size*8;

                for (int i =0; i < size; i++)
                {
                    if (i>0)
                        number = (number>>1);
                    if ((number&1) == 1)
                        ((CheckBox)pnlBitfield.Controls[i.ToString()]).Checked = true;
                    else
                        ((CheckBox)pnlBitfield.Controls[i.ToString()]).Checked = false;
                }
            }
        }

        #region Bit state manipulation tools
        private void btnClrBits_Click(object sender, EventArgs e)
        {
            for (int i = 0; i<pnlBitfield.Controls.Count; i++)
            {
                ((CheckBox)pnlBitfield.Controls[i]).Checked = false;
            }
        }

        private void btnSetBits_Click(object sender, EventArgs e)
        {
            for (int i = 0; i<pnlBitfield.Controls.Count; i++)
            {
                ((CheckBox)pnlBitfield.Controls[i]).Checked = true;
            }
        }

        private void btnInvertBits_Click(object sender, EventArgs e)
        {
            for (int i = 0; i<pnlBitfield.Controls.Count; i++)
            {
                ((CheckBox)pnlBitfield.Controls[i]).Checked = !((CheckBox)pnlBitfield.Controls[i]).Checked;
            }
        }
        #endregion
        #endregion

        #region Consecutive values options
        private void trbBitPositions_Scroll(object sender, EventArgs e)
        {
            nudBitSize.Maximum = (trbBitPositions.Maximum + 1) - trbBitPositions.Value;
        }

        private void nudBitSize_ValueChanged(object sender, EventArgs e)
        {
            int max_value = 1;
            for (int i = 1; i<nudBitSize.Value; i++)
            {
                int power_of_two = 1;
                for (int k = 0; k<i; k++)
                {
                    power_of_two = power_of_two*2;
                }
                max_value += power_of_two;
            }

            nudValue.Maximum = max_value;
        }

        private void nudValue_ValueChanged(object sender, EventArgs e)
        {
            uint calced_val = (uint)nudValue.Value;
            calced_val = calced_val<<trbBitPositions.Value;
            tbCalcedVal.Text = calced_val.ToString();
        }
        #endregion

        private void btnDone_Click(object sender, EventArgs e)
        {
            for (int i =0; i < lbSelectedControlsView.Items.Count; i++)
            {
                IAEUCSetting tmpSetting = (IAEUCSetting)lbSelectedControlsView.Items[i];
                tmpSetting.AEUC_LinkedSetting = true;
                if ((i + 1) < lbSelectedControlsView.Items.Count)
                    tmpSetting.AEUC_NextSettingLink = (IAEUCSetting)lbSelectedControlsView.Items[i + 1];
                else
                    tmpSetting.AEUC_NextSettingLink = (IAEUCSetting)lbSelectedControlsView.Items[0];
            }
            Close();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}